//
// Created by dpdk on 2022/6/22.
//

#include <stdio.h>
#include <malloc.h>
#include "../../../container/double_linked_list/clib_container_double_linked_list.h"

static void linked_list_show(struct clib_container_double_linked_list *list) {
    printf("-----------------\n");
    printf("元素个数 %zu\n", clib_container_double_linked_list_get_current_size(list));
    struct clib_container_double_linked_list_entry *entry_point = clib_container_double_linked_list_get_first(list);
    if (entry_point == NULL) {
        return;
    }
    do {
        printf("%d ", *(clib_uint32_t *) clib_container_double_linked_list_entry_get_data(entry_point));
        entry_point = clib_container_double_linked_list_entry_get_next(entry_point);
    } while (entry_point != NULL);
    printf("\n");

    entry_point = clib_container_double_linked_list_get_last(list);
    if (entry_point == NULL) {
        return;
    }
    do {
        printf("%d ", *(clib_uint32_t *) clib_container_double_linked_list_entry_get_data(entry_point));
        entry_point = clib_container_double_linked_list_entry_get_pre(entry_point);
    } while (entry_point != NULL);
    printf("\n");

    //首元素数据
    entry_point = clib_container_double_linked_list_get_first(list);
    if (entry_point == NULL) {
        return;
    }
    printf("first %d\n", *(clib_uint32_t *) clib_container_double_linked_list_entry_get_data(entry_point));

    //最后元素数据
    entry_point = clib_container_double_linked_list_get_last(list);
    if (entry_point == NULL) {
        return;
    }
    printf("last %d\n", *(clib_uint32_t *) clib_container_double_linked_list_entry_get_data(entry_point));

    printf("元素个数 %zu\n", clib_container_double_linked_list_get_current_size(list));

    printf("-----------------\n");
}


static struct clib_container_double_linked_list *test_create() {
    return clib_container_double_linked_list_create();
}


static void test_add_first() {
    struct clib_container_double_linked_list *list = test_create();
    for (int i = 0; i < 60; ++i) {
        clib_uint32_t *data = malloc(sizeof(clib_uint32_t));
        *data = i;
        clib_container_double_linked_list_insert_first(list, data);
    }
    linked_list_show(list);
}


static void test_add_last() {
    struct clib_container_double_linked_list *list = test_create();
    for (int i = 0; i < 60; ++i) {
        clib_uint32_t *data = malloc(sizeof(clib_uint32_t));
        *data = i;
        clib_container_double_linked_list_insert_last(list, data);
    }
    linked_list_show(list);
}


static void test_add_pre() {
    struct clib_container_double_linked_list *list = test_create();
    for (int i = 0; i < 60; ++i) {
        clib_uint32_t *data = malloc(sizeof(clib_uint32_t));
        *data = i;
        clib_container_double_linked_list_insert_last(list, data);
    }
    struct clib_container_double_linked_list_entry *first_entry = clib_container_double_linked_list_get_first(list);
    if (first_entry != NULL) {
        clib_uint32_t *data = malloc(sizeof(clib_uint32_t));
        *data = 123;
        clib_container_double_linked_list_insert_pre(list, first_entry, data);
        linked_list_show(list);
    }
    struct clib_container_double_linked_list_entry *last_entry = clib_container_double_linked_list_get_last(list);
    if (last_entry != NULL) {
        clib_uint32_t *data = malloc(sizeof(clib_uint32_t));
        *data = 456;
        clib_container_double_linked_list_insert_pre(list, last_entry, data);
        linked_list_show(list);
    }

    struct clib_container_double_linked_list_entry *first_next_entry = clib_container_double_linked_list_entry_get_next(
            first_entry);
    if (first_next_entry != NULL) {
        clib_uint32_t *data = malloc(sizeof(clib_uint32_t));
        *data = 789;
        clib_container_double_linked_list_insert_pre(list, first_next_entry, data);
        linked_list_show(list);
    }
}


static void test_add_next() {
    struct clib_container_double_linked_list *list = test_create();
    for (int i = 0; i < 60; ++i) {
        clib_uint32_t *data = malloc(sizeof(clib_uint32_t));
        *data = i;
        clib_container_double_linked_list_insert_last(list, data);
    }
    struct clib_container_double_linked_list_entry *first_entry = clib_container_double_linked_list_get_first(list);
    if (first_entry != NULL) {
        clib_uint32_t *data = malloc(sizeof(clib_uint32_t));
        *data = 123;
        clib_container_double_linked_list_insert_next(list, first_entry, data);
        linked_list_show(list);
    }
    struct clib_container_double_linked_list_entry *last_entry = clib_container_double_linked_list_get_last(list);
    if (last_entry != NULL) {
        clib_uint32_t *data = malloc(sizeof(clib_uint32_t));
        *data = 456;
        clib_container_double_linked_list_insert_next(list, last_entry, data);
        linked_list_show(list);
    }

    struct clib_container_double_linked_list_entry *first_next_entry = clib_container_double_linked_list_entry_get_next(
            first_entry);
    if (first_next_entry != NULL) {
        clib_uint32_t *data = malloc(sizeof(clib_uint32_t));
        *data = 789;
        clib_container_double_linked_list_insert_next(list, first_next_entry, data);
        linked_list_show(list);
    }
}


static void test_delete_first() {
    struct clib_container_double_linked_list *list = test_create();
    for (int i = 0; i < 60; ++i) {
        clib_uint32_t *data = malloc(sizeof(clib_uint32_t));
        *data = i;
        clib_container_double_linked_list_insert_first(list, data);
    }
    linked_list_show(list);

    for (int i = 0; i < 59; ++i) {
        void *data = clib_container_double_linked_list_delete_first(list);
        if (data != NULL) {
            free(data);
        }
    }
    linked_list_show(list);
}


static void test_delete_last() {
    struct clib_container_double_linked_list *list = test_create();
    for (int i = 0; i < 60; ++i) {
        clib_uint32_t *data = malloc(sizeof(clib_uint32_t));
        *data = i;
        clib_container_double_linked_list_insert_first(list, data);
    }
    linked_list_show(list);

    for (int i = 0; i < 50; ++i) {
        void *data = clib_container_double_linked_list_delete_last(list);
        if (data != NULL) {
            free(data);
        }
    }
    linked_list_show(list);
}



static void test_find_by_index() {
    struct clib_container_double_linked_list *list = test_create();
    for (int i = 0; i < 60; ++i) {
        clib_uint32_t *data = malloc(sizeof(clib_uint32_t));
        *data = i;
        clib_container_double_linked_list_insert_first(list, data);
    }
    linked_list_show(list);

    for (int i = 0; i < 100; ++i) {
        struct clib_container_double_linked_list_entry *entry = clib_container_double_linked_list_get_entry_by_index(
                list, i);
        if (entry == NULL) {
            continue;
        }
        void *data = clib_container_double_linked_list_entry_get_data(entry);
        printf("get data %d %d\n", i, *(clib_uint32_t *) (data));
    }
}



static void test_delete_by_index() {
    struct clib_container_double_linked_list *list = test_create();

    for (int i = 0; i < 60; ++i) {
        clib_uint32_t *data = malloc(sizeof(clib_uint32_t));
        *data = i;
        clib_container_double_linked_list_insert_last(list, data);
    }
    linked_list_show(list);

//    for (int i = 0; i < 100; ++i) {
//        void *data = clib_container_double_linked_list_delete_entry_by_index(
//                list, 0);
//        if (data == NULL) {
//            continue;
//        }
//        printf("delete data %d\n", *(clib_uint32_t *) (data));
//        free(data);
//    }



//    for (int i = 100; i >= 0; --i) {
//        void *data = clib_container_double_linked_list_delete_entry_by_index(
//                list, i);
//        if (data == NULL) {
//            continue;
//        }
//        printf("delete data %d\n", *(clib_uint32_t *) (data));
//        free(data);
//    }

    for (int i = 0; i < 60; ++i) {
        void *data = clib_container_double_linked_list_delete_entry_by_index(
                list, 1);
        if (data == NULL) {
            continue;
        }
        printf("delete data %d\n", *(clib_uint32_t *) (data));
        free(data);
    }
    void *data = clib_container_double_linked_list_delete_entry_by_index(
            list, 0);
    if (data != NULL) {
        printf("delete data %d\n", *(clib_uint32_t *) (data));
        free(data);
    }

    linked_list_show(list);
}


static void test_delete_item() {
    struct clib_container_double_linked_list *list = test_create();

    for (int i = 0; i < 60; ++i) {
        clib_uint32_t *data = malloc(sizeof(clib_uint32_t));
        *data = i;
        clib_container_double_linked_list_insert_last(list, data);
    }
    linked_list_show(list);
    for (int i = 0; i < 1; ++i) {
        struct clib_container_double_linked_list_entry *find_entry = clib_container_double_linked_list_get_entry_by_index(
                list, 59);
        if (find_entry != NULL) {
            void *data = clib_container_double_linked_list_delete(list, find_entry);
            if (data != NULL) {
                free(data);
            }
        }
    }
    linked_list_show(list);
}



static void test_replace() {

    struct clib_container_double_linked_list *list = test_create();

    for (int i = 0; i < 60; ++i) {
        clib_uint32_t *data = malloc(sizeof(clib_uint32_t));
        *data = i;
        clib_container_double_linked_list_insert_last(list, data);
    }
    linked_list_show(list);

    clib_uint32_t *new_data = malloc(sizeof(clib_uint32_t));
    *new_data = 666;
    struct clib_container_double_linked_list_entry *entry = clib_container_double_linked_list_get_entry_by_index(list,
                                                                                                                 30);
    void *replaced_data = clib_container_double_linked_list_replace(list, entry, new_data);
    free(replaced_data);
    linked_list_show(list);

    clib_uint32_t *new_data2 = malloc(sizeof(clib_uint32_t));
    *new_data2 = 888;
    replaced_data = clib_container_double_linked_list_replace_first(list, new_data2);
    free(replaced_data);
    linked_list_show(list);

    clib_uint32_t *new_data3 = malloc(sizeof(clib_uint32_t));
    *new_data3 = 999;
    replaced_data = clib_container_double_linked_list_replace_last(list, new_data3);
    free(replaced_data);
    linked_list_show(list);
}



static void test_move() {

    struct clib_container_double_linked_list *list = test_create();

    for (int i = 0; i < 60; ++i) {
        clib_uint32_t *data = malloc(sizeof(clib_uint32_t));
        *data = i;
        clib_container_double_linked_list_insert_last(list, data);
    }
    linked_list_show(list);

//    struct clib_container_double_linked_list_entry *entry1 = clib_container_double_linked_list_get_entry_by_index(list,
//                                                                                                                  59);
//
//    struct clib_container_double_linked_list_entry *entry2 = clib_container_double_linked_list_get_entry_by_index(list,
//                                                                                                                  0);
//    clib_container_double_linked_list_moveto_next(list, entry1, entry2);
//    linked_list_show(list);

//    struct clib_container_double_linked_list_entry *entry1 = clib_container_double_linked_list_get_entry_by_index(list,
//                                                                                                                  1);
//
//    struct clib_container_double_linked_list_entry *entry2 = clib_container_double_linked_list_get_entry_by_index(list,
//                                                                                                                  59);
//    clib_container_double_linked_list_moveto_pre(list, entry1, entry2);
//    linked_list_show(list);

    for (int i = 0; i < 30; ++i) {
        struct clib_container_double_linked_list_entry *entry1 = clib_container_double_linked_list_get_entry_by_index(
                list,
                59);

        struct clib_container_double_linked_list_entry *entry2 = clib_container_double_linked_list_get_entry_by_index(
                list,
                0);
        clib_container_double_linked_list_moveto_pre(list, entry1, entry2);
        linked_list_show(list);
    }

}

static void clib_container_double_linked_list_test_main() {
//    test_add_first();
//    test_add_last();
//    test_add_pre();
//    test_add_next();
//    test_delete_first();
//    test_delete_last();
//    test_find_by_index();
//    test_delete_by_index();
//    test_delete_item();
//    test_replace();
    test_move();
}
